/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "set_key_event_plugin.h"

#include "common_event_manager.h"
#include "common_event_support.h"
#include "ipolicy_manager.h"
#include "array_int_serializer.h"
#include "edm_constants.h"
#include "edm_errors.h"
#include "edm_ipc_interface_code.h"
#include "func_code_utils.h"
#include "iplugin_manager.h"
#include "set_key_event_serializer.h"

namespace OHOS {
namespace EDM {

const std::vector<int> keyEvents = {
    static_cast<int32_t>(KeyEvent::POWER),
    static_cast<int32_t>(KeyEvent::VOLUME_UP),
    static_cast<int32_t>(KeyEvent::VOLUME_DOWN),
    static_cast<int32_t>(KeyEvent::HOME),
    static_cast<int32_t>(KeyEvent::BACK),
    static_cast<int32_t>(KeyEvent::MENU),
};
const std::vector<int> keyPolicy = {static_cast<int32_t>(KeyPolicy::INTERCEPTION),
    static_cast<int32_t>(KeyPolicy::CUSTOM)};

const bool REGISTER_RESULT = IPluginManager::GetInstance()->AddPlugin(std::make_shared<SetKeyEventPlugin>());

SetKeyEventPlugin::SetKeyEventPlugin()
{
    policyCode_ = EdmInterfaceCode::SET_KEY_EVENT_POLICY;
    policyName_ = PolicyName::POLICY_SET_KEY_EVENT;
    permissionConfig_.typePermissions.emplace(IPlugin::PermissionType::SUPER_DEVICE_ADMIN,
        EdmPermission::PERMISSION_ENTERPRISE_MANAGE_APPLICATION);
    permissionConfig_.apiType = IPlugin::ApiType::PUBLIC;
    needSave_ = true;
}

ErrCode SetKeyEventPlugin::OnHandlePolicy(std::uint32_t funcCode, MessageParcel &data,
    MessageParcel &reply, HandlePolicyData &policyData, int32_t userId)
{
    EDMLOGI("ManageFreezeExemptedAppsPlugin OnHandlePolicy.");
    uint32_t typeCode = FUNC_TO_OPERATE(funcCode);
    FuncOperateType type = FuncCodeUtils::ConvertOperateType(typeCode);
    std::map<int, int> keyEventsMap = ParserKeyEventMap(data);
    std::map<int, int> currentData;
    SetKeyEventSerializer::GetInstance()->Deserialize(policyData.policyData, currentData);
    std::map<int, int> mergeData;
    SetKeyEventSerializer::GetInstance()->Deserialize(policyData.mergePolicyData, mergeData);
    std::string mergePolicyStr;
    IPolicyManager::GetInstance()->GetPolicy("", GetPolicyName(), mergePolicyStr, userId);
    ErrCode res = EdmReturnErrCode::PARAM_ERROR;
    if (type == FuncOperateType::SET) {
        res = OnSetPolicy(keyEventsMap, currentData, mergeData);
    } else if (type == FuncOperateType::REMOVE) {
        res = OnRemovePolicy(keyEventsMap, currentData, mergeData);
    }
    if (res != ERR_OK) {
        reply.WriteInt32(res);
        return res;
    }
    reply.WriteInt32(ERR_OK);
    std::string afterHandle;
    std::string afterMerge;
    SetKeyEventSerializer::GetInstance()->Serialize(currentData, afterHandle);
    SetKeyEventSerializer::GetInstance()->Serialize(mergeData, afterMerge);
    policyData.isChanged = (policyData.policyData != afterHandle || mergePolicyStr != afterMerge);
    policyData.policyData = afterHandle;
    policyData.mergePolicyData = afterMerge;
    return ERR_OK;
}

ErrCode SetKeyEventPlugin::OnSetPolicy(std::map<int, int> &keyEventsMap,
    std::map<int, int> &currentData, std::map<int, int> &mergeData)
{
    EDMLOGI("ManageFreezeExemptedAppsPlugin OnSetPolicy");
    
    for (const auto& i : keyEventsMap) {
        //检查是否在总集合中
        if ((std::find(keyEvents.begin(), keyEvents.end(), i.first) == keyEvents.end())
            || (std::find(keyPolicy.begin(), keyPolicy.end(), i.second) == keyPolicy.end())) {
                return EdmReturnErrCode::PARAM_ERROR;
            }
        //和mergeData比较，有相同键报策略冲突920010
        auto it = mergeData.find(i.first);
        if (it != mergeData.end()) {
            return EdmReturnErrCode::CONFIGURATION_CONFLICT_FAILED;
        }
        //和currentData比较,有相同键则覆盖，没有相同键则添加到currrentData和mergeData
        currentData[i.first] = i.second;
    }
    for (const auto& j : currentData) {
        mergeData[j.first] = j.second;
    }
    //检查自身冲突
    return ERR_OK;
}

ErrCode SetKeyEventPlugin::OnGetPolicy(std::string &policyData, MessageParcel &data,
    MessageParcel &reply, int32_t userId)
{
    EDMLOGI("SetKeyEventPlugin OnGetPolicy");
    std::map<int, int> keyEventMap;
    SetKeyEventSerializer::GetInstance()->Deserialize(policyData, keyEventMap);
    reply.WriteInt32(keyEventMap.size());
    for (const auto& iter : keyEventMap) {
        reply.WriteInt32(iter.first);
    }
    for (const auto& iter : keyEventMap) {
        reply.WriteInt32(iter.second);
    }
    reply.WriteInt32(ERR_OK);
    return ERR_OK;
}

ErrCode SetKeyEventPlugin::OnRemovePolicy(std::map<int, int> &keyEventsMap,
    std::map<int, int> &currentData, std::map<int, int> &mergeData)
{
    EDMLOGI("SetKeyEventPlugin::OnRemovePolicy");
    if (keyEventsMap.empty()) {
        EDMLOGW("SetKeyEventPlugin OnRemovePolicy  kenEvents is empty.");
        return ERR_OK;
    }
    for (const auto& kv : keyEventsMap) {
        currentData.erase(kv.first);
    }
    for (const auto& j : currentData) {
        mergeData[j.first] = j.second;
    }
    return ERR_OK;
}

std::map<int, int> SetKeyEventPlugin::ParserKeyEventMap(MessageParcel &data)
{
    EDMLOGI("SetKeyEventPlugin::ParserKeyEventMap start");
    std::map<int, int> result;
    int32_t mapSize = -1;
    if (!data.ReadInt32(mapSize)) {
        EDMLOGE("ParserKeyEventMap size error");
        return {};
    }
    std::vector<int> keys(mapSize);
    for (int32_t idx = 0; idx < mapSize; ++idx) {
        keys[idx] = data.ReadInt32();
    }
    std::vector<int> values(mapSize);
    for (int32_t idx = 0; idx < mapSize; ++idx) {
        values[idx] = data.ReadInt32();
    }
    for (int32_t idx = 0; idx < mapSize; ++idx) {
        result[keys[idx]] = values[idx];
    }
    return result;
}

}  // namespace EDM
}  // namespace OHOS
